package org.example.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.codec.digest.DigestUtils;
import org.example.commonapi.domain.Practice;
import org.example.commonapi.domain.PracticeHistory;
import org.example.commonapi.domain.R;
import org.example.commonapi.domain.School;
import org.example.commonapi.domain.StudentParent;
import org.example.commonapi.domain.Suggestion;
import org.example.commonapi.domain.User;
import org.example.commonapi.domain.Video;
import org.example.commonapi.domain.VideoHistory;
import org.example.commonapi.dto.InfoFormDTO;
import org.example.commonapi.dto.LoginInfo;
import org.example.commonapi.dto.StudentDto;
import org.example.commonapi.mapper.PracticeHistoryMapper;
import org.example.commonapi.mapper.PracticeMapper;
import org.example.commonapi.mapper.SchoolMapper;
import org.example.commonapi.mapper.StudentParentMapper;
import org.example.commonapi.mapper.SuggestionMapper;
import org.example.commonapi.mapper.UserMapper;
import org.example.commonapi.mapper.VideoHistoryMapper;
import org.example.commonapi.mapper.VideoMapper;
import org.example.commonapi.util.JwtUtil;
import org.example.commonapi.vo.PieVO;
import org.example.commonapi.vo.StudentVO;
import org.example.commonapi.vo.StudyHistoryVO;
import org.example.commonapi.vo.TagVO;
import org.example.user.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.example.commonapi.domain.Constants.STUDENT_ROLE;

/**
* @author DELL
* @description 针对表【user】的数据库操作Service实现
* @createDate 2024-05-16 20:17:38
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    UserMapper userMapper;

    @Resource
    JwtUtil jwtUtil;

    @Autowired
    PracticeHistoryMapper practiceHistoryMapper;

    @Autowired
    VideoHistoryMapper videoHistoryMapper;

    @Autowired
    PracticeMapper practiceMapper;

    @Autowired
    VideoMapper videoMapper;

    @Autowired
    SchoolMapper schoolMapper;

    @Autowired
    StudentParentMapper studentParentMapper;

    @Autowired
    SuggestionMapper suggestionMapper;

    /**
     * 登录
     * @param username
     * @param password
     * @return
     */
    @Override
    public User login(String username, String password) {
        String passwordMd5= DigestUtils.md5Hex(password);
        //利用用户名进行搜索
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username).eq(User::getPassword, passwordMd5);
        User user = userMapper.selectOne(queryWrapper);
        if ( user != null ) {
            // 更新用户登陆时间
            user.setUpdateTime(LocalDateTime.now());
            userMapper.updateById(user);
        }
        return user;
    }


    /**
     * 注册
     * @param loginInfo
     */
    @Override
    public Long register(LoginInfo loginInfo) {
        //加密
        String passwordMd5= DigestUtils.md5Hex(loginInfo.getPassword());
        loginInfo.setPassword(passwordMd5);
        User user=new User(loginInfo);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        userMapper.insert(user);
        return user.getId();
    }

    /**
     * 通过id获取用户信息
     * @param id
     * @return
     */
    @Override
    public User getById(Long id) {
        return userMapper.selectById(id);
    }

    /**
     * 上传头像
     * @param id
     * @param address
     */
    @Override
    public void uploadHead(Long id, String address) {
        User user=new User();
        user.setId(id);
        user.setHeaderLink(address);
        userMapper.updateById(user);
    }

    /**
     * 查看学生
     * @param schoolName
     * @param username
     * @return
     */
    @Override
    public List<StudentDto> studentList(String schoolName, String username) {
        return userMapper.studentList(schoolName, username,STUDENT_ROLE);
    }

    @Override
    public LoginInfo getInfo(Long id) {
        return userMapper.getInfo(id);
    }

    @Override
    public R<List<StudyHistoryVO>> getStudyHistory(HttpServletRequest request) {
        Long userId = jwtUtil.parseJwt(request.getHeader("token")).getId();
        LambdaQueryWrapper<VideoHistory> videoHistoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        videoHistoryLambdaQueryWrapper.eq(VideoHistory::getUserId,userId);
        videoHistoryLambdaQueryWrapper.between(VideoHistory::getWatchTime, LocalDate.now().withDayOfMonth(1), LocalDate.now());
        List<VideoHistory> videoHistories = videoHistoryMapper.selectList(videoHistoryLambdaQueryWrapper);
        LambdaQueryWrapper<PracticeHistory> practiceHistoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        practiceHistoryLambdaQueryWrapper.eq(PracticeHistory::getStudentId,userId);
        practiceHistoryLambdaQueryWrapper.between(PracticeHistory::getCreateTime, LocalDate.now().withDayOfMonth(1), LocalDate.now());
        List<PracticeHistory> practiceHistories = practiceHistoryMapper.selectList(practiceHistoryLambdaQueryWrapper);
        LocalDate firstDayOfMonth = LocalDate.now().withDayOfMonth(1);
        LocalDate now = LocalDate.now();
        List<StudyHistoryVO> studyHistoryVOS = new ArrayList<>();
        while (!firstDayOfMonth.isEqual(now)){
            // 从videoHistories获取当天观看了多少个视频
            LocalDate finalFirstDayOfMonth = firstDayOfMonth;
            int videoCount = (int) videoHistories.stream().filter(videoHistory -> videoHistory.getWatchTime().toLocalDateTime().toLocalDate().equals(finalFirstDayOfMonth)).count();
            // 从practiceHistories获取当天做了多少个题目
            int practiceCount = (int) practiceHistories.stream().filter(practiceHistory -> practiceHistory.getCreateTime().toLocalDate().equals(finalFirstDayOfMonth)).count();
            StudyHistoryVO studyHistoryVO = new StudyHistoryVO();
            studyHistoryVO.setVideoCount(videoCount);
            studyHistoryVO.setPracticeCount(practiceCount);
            if ( videoCount == 0 && practiceCount == 0 ) {
                studyHistoryVO.setIsStudy(0);
            }else {
                studyHistoryVO.setIsStudy(1);
            }
            studyHistoryVOS.add(studyHistoryVO);
            firstDayOfMonth = firstDayOfMonth.plusDays(1);
        }
        return R.success(studyHistoryVOS);
    }

    @Override
    public R<List<Practice>> getPracticeDetail(HttpServletRequest request) {
        Long userId = jwtUtil.parseJwt(request.getHeader("token")).getId();
        LambdaQueryWrapper<PracticeHistory> practiceHistoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        practiceHistoryLambdaQueryWrapper.eq(PracticeHistory::getStudentId,userId);
        List<PracticeHistory> practiceHistories = practiceHistoryMapper.selectList(practiceHistoryLambdaQueryWrapper);
        if (practiceHistories.isEmpty()) {
            return R.success(new ArrayList<>());
        }
        LambdaQueryWrapper<Practice> practiceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        practiceLambdaQueryWrapper.in(Practice::getId,practiceHistories.stream().map(PracticeHistory::getPracticeId).collect(Collectors.toList()));
        List<Practice> practices = practiceMapper.selectList(practiceLambdaQueryWrapper);
        return R.success(practices);
    }

    @Override
    public R<List<TagVO>> getVideoDetail(HttpServletRequest request) {
        Long userId = jwtUtil.parseJwt(request.getHeader("token")).getId();
        LambdaQueryWrapper<VideoHistory> videoHistoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        videoHistoryLambdaQueryWrapper.eq(VideoHistory::getUserId,userId);
        List<VideoHistory> videoHistories = videoHistoryMapper.selectList(videoHistoryLambdaQueryWrapper);
        if ( videoHistories.isEmpty()) {
            return R.success(new ArrayList<>());
        }
        LambdaQueryWrapper<Video> videoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        videoLambdaQueryWrapper.in(Video::getId,videoHistories.stream().map(VideoHistory::getVideoId).collect(Collectors.toList()));
        List<Video> videoList = videoMapper.selectList(videoLambdaQueryWrapper);
        Map<String,Integer> tagMap = new HashMap<>();
        for (Video video : videoList) {
            String[] split = video.getTag().split(",");
            for ( String tag : split) {
                tagMap.put(tag,tagMap.getOrDefault(tag,0)+1);
            }
        }
        List<TagVO> tagVOS = new ArrayList<>();
        for (Map.Entry<String, Integer> entry : tagMap.entrySet()) {
            TagVO tagVO = new TagVO();
            tagVO.setTagName(entry.getKey());
            tagVO.setFrequency(entry.getValue());
            tagVOS.add(tagVO);
        }
        return R.success(tagVOS);
    }

    @Override
    public R submitRoleInfo(InfoFormDTO infoFormDTO, HttpServletRequest request) {
        System.out.println(infoFormDTO);
        Long userId = jwtUtil.parseJwt(request.getHeader("token")).getId();
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getId,userId);
        User user = userMapper.selectOne(userLambdaQueryWrapper);
        LambdaQueryWrapper<School> schoolLambdaQueryWrapper = new LambdaQueryWrapper<>();
        schoolLambdaQueryWrapper.eq(School::getSchoolName,infoFormDTO.getSchoolName());
        System.out.println(infoFormDTO.getSchoolName());
        School school = schoolMapper.selectOne(schoolLambdaQueryWrapper);
        if ( school == null ) {
            System.out.println("学校不存在");
            return R.error("学校不存在");
        }
        LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
        userQueryWrapper.eq(User::getSchoolId,school.getId());
        userQueryWrapper.eq(User::getNo,infoFormDTO.getNo());
        userQueryWrapper.eq(User::getParentPhone,infoFormDTO.getPhone());
        User existedUser = userMapper.selectOne(userQueryWrapper);
        if ( existedUser == null ) {
            System.out.println("学生不存在");
            return R.error("学生不存在");
        }
        user.setRole(1);
        user.setPhotoLink(infoFormDTO.getPhotoLink());
        userMapper.updateById(user);
        StudentParent studentParent = new StudentParent();
        studentParent.setStudentId(existedUser.getId());
        studentParent.setParentId(userId);
        studentParentMapper.insert(studentParent);
        return R.success();
    }

    @Override
    public R<List<StudentVO>> getMyStudentList(HttpServletRequest request) {
        Long userId = jwtUtil.parseJwt(request.getHeader("token")).getId();
        LambdaQueryWrapper<StudentParent> parentProofLambdaQueryWrapper = new LambdaQueryWrapper<>();
        parentProofLambdaQueryWrapper.eq(StudentParent::getParentId,userId);
        List<StudentParent> studentParents = studentParentMapper.selectList(parentProofLambdaQueryWrapper);
        if ( studentParents == null ) {
            return R.success();
        }
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.in(User::getId,studentParents.stream().map(StudentParent::getStudentId).collect(Collectors.toList()));
        List<User> users = userMapper.selectList(userLambdaQueryWrapper);
        List<StudentVO> studentVOS = new ArrayList<>();
        for (User user : users) {
            StudentVO studentVO = new StudentVO();
            BeanUtils.copyProperties(user,studentVO);
            LambdaQueryWrapper<School> schoolLambdaQueryWrapper = new LambdaQueryWrapper<>();
            schoolLambdaQueryWrapper.eq(School::getId,user.getSchoolId());
            School school = schoolMapper.selectOne(schoolLambdaQueryWrapper);
            studentVO.setSchoolName(school.getSchoolName());
            studentVOS.add(studentVO);
        }
        return R.success(studentVOS);
    }

    @Override
    public R<List<Integer>> getRecentVideo(Long id) {
        // 获取最近七天的每天的视频观看历史记录
        List<Integer> videoHistoryCount = new ArrayList<>();
        for (int i = 0; i < 7; i++) {
            LambdaQueryWrapper<VideoHistory> videoHistoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
            videoHistoryLambdaQueryWrapper.eq(VideoHistory::getUserId,id);
            videoHistoryLambdaQueryWrapper.ge(VideoHistory::getWatchTime,LocalDate.now().minusDays(i));
            videoHistoryLambdaQueryWrapper.le(VideoHistory::getWatchTime,LocalDate.now().minusDays(i-1));
            videoHistoryCount.add(Math.toIntExact(videoHistoryMapper.selectCount(videoHistoryLambdaQueryWrapper)));
        }

        return R.success(videoHistoryCount);
    }

    @Override
    public R<List<Integer>> getRecentPractice(Long id) {
        List<Integer> practiceHistoryCount = new ArrayList<>();
        for (int i = 0; i < 7; i++) {
            LambdaQueryWrapper<PracticeHistory> practiceHistoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
            practiceHistoryLambdaQueryWrapper.eq(PracticeHistory::getStudentId,id);
            practiceHistoryLambdaQueryWrapper.ge(PracticeHistory::getCreateTime,LocalDate.now().minusDays(i));
            practiceHistoryLambdaQueryWrapper.le(PracticeHistory::getCreateTime,LocalDate.now().minusDays(i-1));
            practiceHistoryCount.add(Math.toIntExact(practiceHistoryMapper.selectCount(practiceHistoryLambdaQueryWrapper)));
        }
        return R.success(practiceHistoryCount);
    }

    @Override
    public R submitAdvice(String content) {
        Suggestion suggestion = new Suggestion();
        suggestion.setContent(content);
        suggestion.setCreateTime(LocalDateTime.now());
        suggestionMapper.insert(suggestion);
        return R.success();
    }

    @Override
    public R updateUserInfo(User user,HttpServletRequest request) {
        Long userId = jwtUtil.parseJwt(request.getHeader("token")).getId();
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getId,userId);
        User existedUser = userMapper.selectOne(lambdaQueryWrapper);
        if ( user.getHeaderLink() != null ) {
            existedUser.setHeaderLink(user.getHeaderLink());
        }
        if ( user.getUsername() != null ) {
            existedUser.setUsername(user.getUsername());
        }
        if ( user.getPassword() != null ) {
            existedUser.setPassword(user.getPassword());
        }
        if ( user.getAddress() != null ) {
            existedUser.setAddress(user.getAddress());
        }
        if ( user.getPhotoLink() != null ) {
            existedUser.setPhotoLink(user.getPhotoLink());
        }
        if ( existedUser.getRole() == null && user.getRole() != null ) {
            existedUser.setRole(user.getRole());
        }
        userMapper.updateById(existedUser);
        return R.success();
    }

    @Override
    public R<List<PieVO>> getRecentVideoData(Long id) {
        Map<String,Integer> videoWatchTimeMap = new HashMap<>();
        LambdaQueryWrapper<VideoHistory> videoHistoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        videoHistoryLambdaQueryWrapper.eq(VideoHistory::getUserId,id);
        videoHistoryLambdaQueryWrapper.ge(VideoHistory::getWatchTime,LocalDate.now().minusDays(7));
        videoHistoryLambdaQueryWrapper.le(VideoHistory::getWatchTime,LocalDate.now());
        List<VideoHistory> videoHistoryList = videoHistoryMapper.selectList(videoHistoryLambdaQueryWrapper);
        for (VideoHistory videoHistory : videoHistoryList) {
            LambdaQueryWrapper<Video> videoLambdaQueryWrapper = new LambdaQueryWrapper<>();
            videoLambdaQueryWrapper.eq(Video::getId,videoHistory.getVideoId());
            Video video = videoMapper.selectOne(videoLambdaQueryWrapper);
            System.out.println("找到了视频");
            System.out.println(video);
            if ( videoWatchTimeMap.containsKey(video.getTitle()) ) {
                videoWatchTimeMap.put(video.getTitle(),videoWatchTimeMap.get(video.getTitle())+1);
            } else {
                videoWatchTimeMap.put(video.getTitle(),1);
            }
        }
        List<PieVO> pieVOS = new ArrayList<>();
        videoWatchTimeMap.forEach((k,v) -> {
            PieVO pieVO = new PieVO();
            pieVO.setName(k);
            pieVO.setValue(v);
            pieVOS.add(pieVO);
        });
        return R.success(pieVOS);
    }

    @Override
    public R<List<PieVO>> getRecentPracticeData(Long id) {
        Map<String,Integer> practiceVisitMap = new HashMap<>();
        LambdaQueryWrapper<PracticeHistory> practiceHistoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        practiceHistoryLambdaQueryWrapper.eq(PracticeHistory::getStudentId,id);
        practiceHistoryLambdaQueryWrapper.ge(PracticeHistory::getCreateTime,LocalDate.now().minusDays(7));
        practiceHistoryLambdaQueryWrapper.le(PracticeHistory::getCreateTime,LocalDate.now());
        List<PracticeHistory> practiceHistories = practiceHistoryMapper.selectList(practiceHistoryLambdaQueryWrapper);

        for (PracticeHistory practiceHistory : practiceHistories) {
            LambdaQueryWrapper<Practice> practiceLambdaQueryWrapper = new LambdaQueryWrapper<>();
            practiceLambdaQueryWrapper.eq(Practice::getId,practiceHistory.getPracticeId());
            Practice practice = practiceMapper.selectOne(practiceLambdaQueryWrapper);
            if ( practiceVisitMap.containsKey(practice.getName()) ) {
                practiceVisitMap.put(practice.getName(),practiceVisitMap.get(practice.getName())+1);
            } else {
                practiceVisitMap.put(practice.getName(),1);
            }
        }
        List<PieVO> pieVOS = new ArrayList<>();
        practiceVisitMap.forEach((k,v) -> {
            PieVO pieVO = new PieVO();
            pieVO.setName(k);
            pieVO.setValue(v);
            pieVOS.add(pieVO);
        });
        return R.success(pieVOS);
    }
}